#pragma once
#include "fifo.hpp"
#include <iostream>
#include <string>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#define ShmSize BaseSize
const std::string MyShmPath = "/home/zzy/2024test/Shm";
const int Id = 0x66;
class Shm
{
    bool CreaterGetShm()
    {
        if(_who == Creater)
        {
            _shmid = shmget(_key,ShmSize,IPC_CREAT | IPC_EXCL| 0666);
            if(_shmid>=0)
            std::cout<<"Creater 创建共享内存成功！"<<std::endl;
            return true;
        }
        perror("Creater Shm");
        return false;

    }
    bool UserGetShm()
    {
        if(_who== User)
        {
            _shmid = shmget(_key,ShmSize,IPC_CREAT | 0666);
            if(_shmid>=0)
            std::cout<<"User 创建共享内存成功！"<<std::endl;
            return true;
        }
        perror("User Shm");
        return false;
    }
    void *AttachShm()
    {
        void* addrshm = shmat(_shmid,nullptr,0);
        if(addrshm==nullptr) perror("AttachShm");
        std::cout<<"挂接成功!"<<std::endl;
        return addrshm;
    }
    void DetachShm(void *addrshm)
    {
        if(addrshm)
        {
            shmdt(addrshm);
            std::cout<<"断开链接"<<std::endl;
        }
    }


public:
    Shm(const std::string &path, const int id, int who)
        : _path(path), _id(id), _who(who), _addrshm(nullptr)
    {
        _key = ftok(_path.c_str(),id);
        if (_key < 0)
            perror("ftok");
        if (who == Creater)
            CreaterGetShm();
        if (who == User)
            UserGetShm();
        _addrshm = AttachShm();
        std::cout<<"key:"<<_key<<std::endl;
    }
    ~Shm()
    {
        if(_who == Creater)
        {
            int res =shmctl(_shmid,IPC_RMID,nullptr);
            if(res != 0) perror("~Shm");
            std::cout<<"Creater remove Shm";
        }
        DetachShm(_addrshm);
    }
    void* Addr()
    {
        return _addrshm;
    }
    void Zero()
    {
        if(_addrshm)
        memset(_addrshm,0,ShmSize);
    }

private:
    int _who;
    std::string _path;
    int _id;
    int _shmid;
    key_t _key;
    void *_addrshm;
};